<?php
/**
 * Created by PhpStorm.
 * User: bzg
 * Date: 2019/11/27
 * Time: 14:57
 */

namespace App\Extend\SysExtend\Middleware;

use EasySwoole\Component\Di;
use EasySwoole\Http\Request;
use EasySwoole\Http\Response;

/**
 * 中间件管理中心
 * Class MiddlewareManager
 * @package App\Extend\Middleware
 */
class MiddlewareManager
{
    /**
     * @var array 中间件规则
     */
    private $middleware_rule;

    /**
     * 从中间件配置文件中读取中间件
     */
    public function saveRuleToFile()
    {
        $this->middleware_rule = Di::getInstance()->get('extendConfig')->get('middleware');
        Di::getInstance()->set('middlewareManager',$this);
    }


    /**
     * 执行中间件前置方法
     * @param Request $request
     * @param Response $response
     * @return bool
     */
    public function handelBefore(Request $request, Response $response)
    {
        $middleware_list = $this->checkUri($this->getUri($request));
        if(!empty($middleware_list)) {
            foreach ($middleware_list as $mw) {
                // 返回false则终止执行
                if((new $mw())->before($request, $response) === false) {
                    return false;
                }
            }
        }
    }


    /**
     * 执行中间件后置方法
     * @param Request $request
     * @param Response $response
     */
    public function handelAfter(Request $request, Response $response)
    {
        $middleware_list = $this->checkUri($this->getUri($request));
        if(!empty($middleware_list)) {
            // 倒序一下中间件
            $middleware_list = array_reverse($middleware_list);
            foreach ($middleware_list as $mw) {
                // 返回false则断开连接
                if((new $mw())->after($request, $response) === false) {
                    $response->end();
                }
            }
        }
    }

    /**
     * 获取当前请求的uri
     * @param Request $request
     * @return string
     */
    private function getUri(Request $request) : string
    {
        return $request->getSwooleRequest()->server['request_uri'];
    }

    /**
     * 判断当前请求url是否在规则中
     * @param string $uri 请求的uri
     * @return array|mixed 中间件数组
     */
    private function checkUri(string $uri) : array
    {
        if(!empty($this->middleware_rule)) {
            $mw_list = [];
            foreach ($this->middleware_rule as $rule => $mw) {
                // 解析规则中的*号
                $rule_prefix = explode('*',$rule)[0];
                // 处理规则中的 /
                $rule_prefix = str_replace('/','\\/',$rule_prefix);
                // 正则匹配当前uri是否和规则前缀符合
                if(preg_match('/^'.$rule_prefix.'/',$uri)) {
                    $mw_list = array_merge($mw_list,$mw);
                }
            }
            return array_unique($mw_list);
        }
        return [];
    }

}